package com.sq.partner.manager.util;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2003</p>
 * <p>Company: </p>
 * @author unascribed
 * @version 1.0
 */
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.sql.Timestamp;
import java.text.*;
import java.math.BigDecimal;


/**
 * <p>Operations on the conversion of Data and String</p>
 * <p> format char define:</p>
 * <p> G        era designator          (Text)              AD </p>
 * <p> y        year                    (Number)            1996 </p>
 * <p> M        month in year           (Text & Number)     July & 07 </p>
 * <p> d        day in month            (Number)            10 </p>
 * <p> h        hour in am/pm (1~12)    (Number)            12 </p>
 * <p> H        hour in day (0~23)      (Number)            0  </p>
 * <p> m        minute in hour          (Number)            30 </p>
 * <p> s        second in minute        (Number)            55 </p>
 * <p> S        millisecond             (Number)            978 </p>
 * <p> E        day in week             (Text)              Tuesday </p>
 * <p> D        day in year             (Number)            189 </p>
 * <p> F        day of week in month    (Number)            2 (2nd Wed in July) </p>
 * <p> w        week in year            (Number)            27 </p>
 * <p> W        week in month           (Number)            2  </p>
 * <p> a        am/pm marker            (Text)              PM </p>
 * <p> k        hour in day (1~24)      (Number)            24 </p>
 * <p> K        hour in am/pm (0~11)    (Number)            0  </p>
 * <p> z        time zone               (Text)              Pacific Standard Time </p>
 * <p> '        escape for text         (Delimiter)            </p>
 * <p> ''       single quote            (Literal)           '  </p>
 *
 * @author lehf
 * @since 1.0
 * @version $Id: DateUtil.java
 */

public class DateUtil {

	public static int getDays(Date startday, Date endday) {
    	if(null==startday||null==endday){
    		return 0;
    	}
    	if(startday == endday){
    		return 1;
    	}
		if (startday.after(endday)) {
			Date cal = startday;
			startday = endday;
			endday = cal;
		}
		long sl = startday.getTime();
		long el = endday.getTime();
		long ei = el - sl;
		int day = (int)(ei / (1000 * 60 * 60 * 24)) ;
		if(day == 0){
			return 1;
		}
		return  day;
	}
    
    public static int getAge(String timeString) throws Exception{

		int age = 0;
		GregorianCalendar birthday = new GregorianCalendar();
		GregorianCalendar nowTime = new GregorianCalendar();

		Date time = parse(timeString,"yyyy/MM/dd");
		if (timeString == null || "".equals(timeString)) {
			return 0;
		}
		birthday.setTime(time);

		age = nowTime.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
		
		if(age<=0){
			return 0;
		}
		if (nowTime.get(Calendar.MONTH) > birthday.get(Calendar.MONTH)) {
			return age;
		} else if (nowTime.get(Calendar.MONTH) < birthday.get(Calendar.MONTH)) {
			return --age;
		} else {
			if (nowTime.get(Calendar.DAY_OF_MONTH) >= birthday.get(Calendar.DAY_OF_MONTH)) {
				return age;
			} else {
				return --age;
			}
		}
	}
	
    /**
     * <p>get Date from a formated string</p>
     *
     * <pre>
     * getDateFromString("031009")
     * getDateFromString("20031009")
     * </pre>
     *
     * @param strDate  the formated data String
     * @return a date associate with the parameter strDate
     */
    public static Date parse(String strDate) throws Exception {
    	if (null == strDate || "".equals(strDate)) return null;
    	
        int length = strDate.length();
        if (length == 6) {
            return parse(strDate, "yyMMdd");
        }
        if (length == 8) {
            return parse(strDate, "yyyyMMdd");
        }
        if (length == 10 && strDate.contains("/")) {
        	return parse(strDate, "yyyy/MM/dd");
        }
        if (length == 10) {
            return parse(strDate, "yyyy-MM-dd");
        }
        return parse(strDate, "yy-MM-dd");
    }

    /**
     * <p>get Date from a formated string</p>
     *
     * <pre>
     * getDateFromString("031009", "yyMMdd")
     * getDateFromString("20031009", "yyyyMMdd")
     * </pre>
     *
     * @param strDate  the formated data String
     * @param format   the format of the strDate
     * @return a date associate with the parameter strDate
     */
    public static Date parse(String strDate, String format) throws Exception {
        try {
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            ParsePosition pos = new ParsePosition(0);
            return formatter.parse(strDate, pos);
        } catch (Exception ex) {
            throw new Exception(ex);
        }
    }

    /**
     * <p>get String from a Date</p>
     *
     * <pre>
     * getDateFromString(new Date(System.currentTimeMillis()))
     * </pre>
     *
     * @param dt  the data to be convert
     * @return a String associate with the parameter dt
     */
    public static String format(Date dt) throws Exception {
        return format(dt, "yyyyMMdd");
    }

    /**
     * <p>get String from a Date</p>
     *
     * <pre>
         * getDateFromString(new Date(System.currentTimeMillis()), "yyMMdd HH:mm:ss") = "030910 12:23:30"
     * </pre>
     *
     * @param dt  the data to be convert
     * @param format   the format to be returned
     * @return a String associate with the parameter dt
     */
    public static String format(Date dt, String format) throws Exception {
        try {
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            return formatter.format(dt);
        } catch (Exception ex) {
            throw new Exception(ex);
        }
    }

    /**
     * <p>get the interval days between two date</p>
     *
     * <pre>
     * diffDate(dt1, dt2) = 2 // suppose dt1="030902" & dt2="030831"
     * </pre>
     *
     * @param dt1  the first data
     * @param dt2  the second data
     * @return the interval days between dt1 and dt2
     */
    public static int diffDate(Date dt1, Date dt2) {
        long date1 = dt1.getTime();
        long date2 = dt2.getTime();
        if (date1 > date2) {
            return (int) ( (date1 - date2) / (24 * 3600 * 1000.0) + 0.5);
        }

        return (int) ( (date2 - date1) / (24 * 3600 * 1000.0) + 0.5);
    }

    /**
     * <p>get the interval years between two date</p>
     * precision: second
     */
    public static int diffYear(Date beforeDate, Date afterDate) throws Exception {
        Calendar cal = Calendar.getInstance();
        cal.setTime(afterDate);
        int year = cal.get(Calendar.YEAR); //获得年份

        cal.setTime(beforeDate);
        int year1 = cal.get(Calendar.YEAR); //获得年份

        int t = year - year1; //得到年差

        String md = format(afterDate, "yyyyMMdd HHmmss").substring(4);
        if ("0229".equals(md.substring(0, 4))) {
            md = "0228" + md.substring(4);
        }
        md = "2000" + md;
        String md1 = format(beforeDate, "yyyyMMdd HHmmss").substring(4);
        if ("0229".equals(md1.substring(0, 4))) {
            md1 = "0228" + md1.substring(4);
        }
        md1 = "2000" + md1;

        if (parse(md,
                              "yyyyMMdd HHmmss").before(parse(md1, "yyyyMMdd HHmmss"))) {
            t = t - 1;
        }

        return t;
    }

    /**
     * <p>get the interval days between two date described by formater "yy-MM-dd"</p>
     *
     * <pre>
     * diffDate("20030902", "20030904") = 2
     * </pre>
     *
     * @param dt1  the first data
     * @param dt2  the second data
     * @return the interval days between dt1 and dt2
     */
    public static int diffDate(String dt1, String dt2) throws Exception {
        return diffDate(dt1, dt2, "yyyyMMdd");
    }

    /**
     * <p>get the interval days between two date described by desired formater</p>
     *
     * <pre>
     * diffDate("03-09-02", "03-09-04", "yy-MM-dd") = 2
     * </pre>
     *
     * @param dt1  the first data
     * @param dt2  the second data
     * @param format the formater of the dt1 and dt2
     * @return the interval days between dt1 and dt2
     */
    public static int diffDate(String dt1, String dt2, String format) throws Exception {
        return diffDate(parse(dt1, format), parse(dt2, format));
    }

    /**
         * <p>Adds the specified (signed) amount of day to the given date, based on the calendar's rules</p>
     *
     * <pre>
     * addDaysToDate(dt1, 2) = dt // if dt1="03-09-02" then dt="03-09-04"
     * </pre>
     *
     * @param dt1  the base data
     * @param days days to be added
     * @return the new date
     */
    public static Date addDaysToDate(Date dt1, int days) {
        Calendar cale = Calendar.getInstance();
        cale.setTime(dt1);
        cale.add(Calendar.DATE, days);
        return cale.getTime();
    }

    /**
         * <p>Adds the specified (signed) amount of day to the given date, based on the calendar's rules</p>
     *
     * <pre>
     * addDaysToDate("20030902", 2) = dt // dt="20030904"
     * </pre>
     *
     * @param dt1  the base data
     * @param days days to be added
     * @return the new date
     */
    public static Date addDaysToDate(String dt1, int days) throws Exception {
        return addDaysToDate(dt1, "yyyyMMdd", days);
    }

    /**
         * <p>Adds the specified (signed) amount of day to the given date, based on the calendar's rules</p>
     *
     * <pre>
     * addDaysToDate("03-09-02", "yy-MM-dd", 2) = dt // dt="03-09-04"
     * </pre>
     *
     * @param dt1  the base data
     * @param format the format of the dt1
     * @param days days to be added
     * @return the new date
     */
    public static Date addDaysToDate(String dt1, String format, int days) throws Exception {
        return addDaysToDate(parse(dt1, format), days);
    }

    public static java.util.Date addMonthsToDate(java.util.Date dt1, int months) {
        Calendar cale = Calendar.getInstance();
        cale.setTime(dt1);
        cale.add(Calendar.MONTH, months);
        return cale.getTime();
    }

    public static java.util.Date addMonthsToDate(String dt1, String format,
                                                 int months) throws Exception {
        return addMonthsToDate(parse(dt1, format), months);
    }

    /**
     * <p>get the system current date</p>
     *
     * <pre>
     * getCurrentDate() = "20030908"
     * </pre>
     *
     * @return the current date
     */
    public static String getCurrentDate() throws Exception {
        return getCurrentDateTime("yyyyMMdd");
    }

    /**
     * <p>get the system current time</p>
     *
     * <pre>
     * getCurrentTime() = "121208"
     * </pre>
     *
     * @return the current time
     */
    public static String getCurrentTime() throws Exception {
        return getCurrentDateTime("HHmmss");

    }

    /**
     * <p>get the system current date and time</p>
     *
     * <pre>
     * getCurrentTime() = "20030912 121208"
     * </pre>
     *
     * @return the current date and time
     */
    public static String getCurrentDateTime() throws Exception {
        return getCurrentDateTime("yyyyMMdd HHmmss");
    }

    /**
     * <p>get the system current date and time</p>
     *
     * <pre>
     * getCurrentTime("yy-MM-dd HH:mm:ss") = "03-09-12 12:12:08"
     * </pre>
     *
     * @return the current date and time
     */
    public static String getCurrentDateTime(String format) throws Exception {
        return format(new Date(System.currentTimeMillis()), format);
    }

    /**
     * 获取给定日期对象的天
     *
     * @param date 日期对象
     * @return 天
     */
    public static int getDay(final Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DATE);
    }


    /**
     * 返回给定的beforeDate比afterDate早的月数。如果beforeDate晚于afterDate，则
     * 返回负数。
     *
     * @param beforeDate 要比较的早的日期
     * @param afterDate 要比较的晚的日期
     * @return beforeDate比afterDate早的月数，负数表示晚。
     */
    public static int beforeMonths(final Date beforeDate, final Date afterDate) {
        Calendar beforeCalendar = Calendar.getInstance();
        beforeCalendar.setTime(beforeDate);
        beforeCalendar.set(Calendar.DATE, 1);
        beforeCalendar.set(Calendar.HOUR, 0);
        beforeCalendar.set(Calendar.SECOND, 0);
        beforeCalendar.set(Calendar.MINUTE, 0);
        Calendar afterCalendar = Calendar.getInstance();
        afterCalendar.setTime(afterDate);
        afterCalendar.set(Calendar.DATE, 1);
        afterCalendar.set(Calendar.HOUR, 0);
        afterCalendar.set(Calendar.SECOND, 0);
        afterCalendar.set(Calendar.MINUTE, 0);
        boolean positive = true;
        if (beforeDate.after(afterDate)) {
            positive = false;
        }
        int beforeMonths = 0;
        while (true) {
            boolean yearEqual = beforeCalendar.get(Calendar.YEAR) ==
                afterCalendar.get(Calendar.YEAR);
            boolean monthEqual = beforeCalendar.get(Calendar.MONTH) ==
                afterCalendar.get(Calendar.MONTH);
            if (yearEqual && monthEqual) {
                break;
            } else {
                if (positive) {
                    beforeMonths++;
                    beforeCalendar.add(Calendar.MONTH, 1);
                } else {
                    beforeMonths--;
                    beforeCalendar.add(Calendar.MONTH, -1);
                }
            }
        }
        return beforeMonths;
    }

    /**
     * 获取beforeDate和afterDate之间相差的完整月数，精确到天。负数表示晚。
     *
     * @param beforeDate 要比较的早的日期
     * @param afterDate 要比较的晚的日期
     * @return beforeDate比afterDate早的完整月数，负数表示晚。
     */
    public static int beforeRoundMonths(final Date beforeDate, final Date afterDate) {
        Date bDate = beforeDate;
        Date aDate = afterDate;
        boolean positive = true;
        if (beforeDate.after(afterDate)) {
            positive = false;
            bDate = afterDate;
            aDate = beforeDate;
        }
        int beforeMonths = beforeMonths(bDate, aDate);
        int bDay = getDay(bDate);
        int aDay = getDay(aDate);
        if (aDay < bDay) {
        //beforeMonths--;
        }

        if (positive) {
            return beforeMonths;
        } else {
            return new BigDecimal(beforeMonths).negate().intValue() - 1;
        }
    }
    public static String getLastDate(List list) throws Exception{
    	Date bigDate = new Date();
    	if(bigDate.compareTo(bigDate)==1)return"";
    	for(int i=0;i<list.size();i++){
    		String time = (String)list.get(i);
    		Date sDate = DateUtil.parse(time);
    		if(bigDate.compareTo(sDate)<0){
    			bigDate = sDate;
    		}
    	}
    	return DateUtil.format(bigDate,"yyyy-MM-dd");
    }
    public static void main(String args[]) throws Exception {
        /**
             System.out.println(getStringFromDate(new Date(System.currentTimeMillis()), "yy-MM-dd, HH:mm:ss"));
                 System.out.println(getStringFromDate(new Date(System.currentTimeMillis()), "EE MM dd HH:mm:ss yyyy"));
                 Calendar cale1 = Calendar.getInstance();
                 Calendar cale2 = Calendar.getInstance();
                 cale1.set(2003, 8, 25, 0, 30, 30);
                 cale2.set(2003, 7, 30, 02, 30, 30);
             System.out.println("getStringFromDate : "+getStringFromDate(cale2.getTime(), "yy-M-d HH:mm:ss"));
                 System.out.println("diffDate :"+diffDate(cale1.getTime(), cale2.getTime()));
             System.out.println("addDaysToDate :"+addDaysToDate(cale1.getTime(), -25).toString());
                 System.out.println("getDateFromString :"+getDateFromString("080915").toString());
                 System.out.println("getDateFromString :"+getDateFromString(getStringFromDate(new Date(System.currentTimeMillis()), "EEE MM dd HH:mm:ss yyyy"), "EEE MM dd HH:mm:ss yyyy").toString());
                 System.out.println(diffDate("03-0825", "03-0925", "yy-MMdd"));
             System.out.println(getFormat2FromFormat1(getCurrentDate(), "yyyyMMdd", "yyyy/MM/dd HHmmss"));
         **/
//        String test = "20030825 14:30"; //getStringFromDate(cale2.getTime(), "YY-M-D HH:NN:SS");
//        System.out.println("getDateFromString :" + test + "-> " +
//                           getDateFromString(test, "yyyyMMdd H:mm"));
//        System.out.println(DateUtil.getStringFromDate(new Timestamp(System.currentTimeMillis()),
//            "yy-M-D HH:mm:SS"));
//        System.out.println(test.substring(test.indexOf(":") - 2, test.indexOf(":")));
//        System.out.println(DateUtil.getDateFromString("0921", "MMdd"));
//        System.out.println(DateUtil.beforeMonths(getDateFromString("20060228"),
//                                                 getDateFromString("20060829")));
//        System.out.println(DateUtil.diffYear(getDateFromString("20000229 152828","yyyyMMdd HHmmss"),
//                                             getDateFromString("20060228 152828","yyyyMMdd HHmmss")));
    	
    	List list = new ArrayList();
    	list.add("2010-01-01");
    	list.add("2010-03-05");
    	list.add("2010-12-12");
    	list.add("2010-12-10");
    	String s = getLastDate(list);
    	System.out.println(s);
    }
    /**
     * 判断是否是标准的日期 是就返回true 错误就返回false
     * @param date
     * @return
     */
    public static boolean isDate(String date)
	{
		/**
		 * 判断日期格式和范围
		 */
		String rexp = "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";
		
		Pattern pat = Pattern.compile(rexp);  
		
		Matcher mat = pat.matcher(date);  
		
		boolean dateType = mat.matches();

		return dateType;
	}
    
    /** 从交易系统copy
	 * 计算两个日期的天数差
	 * 不足一天 不计算 
	 * 结束日期如果是 23:59:59 认为足一天
	 * 结束日期如果是 00:00:00 则认为是第二天00:00:00  
	 * @param effectDate
	 * @param termDate
	 * @return
	 * @throws ParseException 
	 */
	public static long timeOneDay = 24*60*60 * 1000;
	public static long time235959 = timeOneDay - 1000;
	public static long time1970 = 0;
	static{
		try{
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			time1970 = sdf.parse("1970-01-01 00:00:00").getTime();
		}catch(Exception e){
		}
	}
	
	public static long calcDays(Date effectDate,Date termDate){
		long termDateTime = termDate.getTime();
		long termDateTimeLeft = (termDateTime-time1970) % timeOneDay;
		
		if( termDateTimeLeft >= time235959){//23:59:59认为是够一天
			termDateTime = termDateTime - termDateTimeLeft + timeOneDay;
		}
		
		if(termDateTimeLeft == 0){//00:00:00 加一天
			termDateTime = termDateTime + timeOneDay;
		}
		
		long timeBetween = termDateTime - effectDate.getTime();
		
		return timeBetween/timeOneDay;
	}
	
	public static Date getNowDate(String format) throws ParseException{
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        Date formatDate = simpleDateFormat.parse(simpleDateFormat.format(date));
        return formatDate;
    }
	
	public static Timestamp getNowTimestamp(){
        return new Timestamp(new Date().getTime());
    }
}
